using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using HslCommunication;
using LambdaBuilder.Resolver;
using Opc.Ua;
using Opc.Ua.Server;
using Catastrophe.AutoSulution.EDC;
using Catastrophe.Common.AttributeEx;

namespace HslCommunicationEx.OpcUa.Server
{
	public class PeanutOpcUaNodeManager : CustomNodeManager2
	{
		private IList<IReference> _references;

		private Dictionary<string, BaseDataVariableState> _varDic = new Dictionary<string, BaseDataVariableState>();

		private Dictionary<string, FolderState> _folderDic = new Dictionary<string, FolderState>();

		private Dictionary<string, MethodState> _methodDic = new Dictionary<string, MethodState>();

		private static object AddNodesLock = new object();

		private List<OpcUaNode> _listNotes = new List<OpcUaNode>();

		private Dictionary<Type, OpcUaApiAttribute> _dicOpcApi = new Dictionary<Type, OpcUaApiAttribute>();

		public List<OpcUaNode> ListNotes
		{
			get
			{
				return this._listNotes;
			}
			set
			{
				this._listNotes = value;
			}
		}

		public string NodeSplitFlag { get; set; } = "/";


		public int MaxNodeId
		{
			get
			{
				if (this._listNotes.Count > 0)
				{
					return this._listNotes.Max((OpcUaNode x) => x.NodeId);
				}
				return 0;
			}
		}

		public int NodeIdIncrease => this.MaxNodeId + 1;

		public PeanutOpcUaNodeManager(IServerInternal server, ApplicationConfiguration configuration, params string[] namespaceUris)
			: base(server, configuration, namespaceUris)
		{
		}

		public void AddNodes(List<OpcUaNode> list)
		{
			lock (PeanutOpcUaNodeManager.AddNodesLock)
			{
				this.AddNodes(list.ToArray());
			}
		}

		public void AddNodes(params OpcUaNode[] nodes)
		{
			lock (PeanutOpcUaNodeManager.AddNodesLock)
			{
				foreach (OpcUaNode each in nodes)
				{
					OpcUaNode opcUaNode = this._listNotes.FirstOrDefault((OpcUaNode x) => x.NodeName == each.NodeName && x.ParentNodeId == each.ParentNodeId);
					if (opcUaNode != null)
					{
						if (opcUaNode.NodeType != 0)
						{
							continue;
						}
						IEnumerable<OpcUaNode> enumerable = nodes.Where((OpcUaNode x) => x.ParentNodeId == each.NodeId);
						foreach (OpcUaNode item in enumerable)
						{
							if (item.ParentNodeId != opcUaNode.NodeId)
							{
								item.ParentNodeId = opcUaNode.NodeId;
							}
						}
					}
					else
					{
						this._listNotes.Add(each);
					}
				}
			}
		}

		protected override NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary<NodeId, NodeState> cache)
		{
			lock (base.Lock)
			{
				if (!this.IsNodeIdInNamespace(nodeId))
				{
					return null;
				}
				if (base.PredefinedNodes == null)
				{
					return null;
				}
				if (!base.PredefinedNodes.TryGetValue(nodeId, out var value))
				{
					return null;
				}
				NodeHandle nodeHandle = new NodeHandle();
				nodeHandle.NodeId = nodeId;
				nodeHandle.Node = value;
				nodeHandle.Validated = true;
				return nodeHandle;
			}
		}

		protected override NodeState ValidateNode(ServerSystemContext context, NodeHandle handle, IDictionary<NodeId, NodeState> cache)
		{
			if (handle == null)
			{
				return null;
			}
			if (handle.Validated)
			{
				return handle.Node;
			}
			return null;
		}

		public override void CreateAddressSpace(IDictionary<NodeId, IList<IReference>> externalReferences)
		{
			lock (base.Lock)
			{
				if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out this._references))
				{
					externalReferences[ObjectIds.ObjectsFolder] = (this._references = new List<IReference>());
				}
				try
				{
					OpcUaNode parent = this.CreateRootNode();
					this.CreateVarNodes(parent);
					List<OpcUaNode> list = this.CreateMethods();
					this.AddNodes(list);
					this.GenerateNodes(this._listNotes, this._references);
					this.AfteCreateNodes();
				}
				catch (Exception ex)
				{
					Console.ForegroundColor = ConsoleColor.Red;
					Console.WriteLine("调用接口初始化触发异常:" + ex.Message);
					Console.ResetColor();
				}
			}
		}

		protected virtual void AfteCreateNodes()
		{
		}

		protected virtual OpcUaNode CreateRootNode()
		{
			OpcUaNode opcUaNode = new OpcUaNode
			{
				NodeType = OpcUaNodeTypeEnum.Folder,
				NodeName = "PeanutOpcUa",
				DisplayName = "PeanutOpcUaServer",
				Description = "OPC UA Server"
			};
			OpcUaNode opcUaNode2 = new OpcUaNode
			{
				NodeType = OpcUaNodeTypeEnum.Folder,
				NodeName = "Variables",
				ParentNodeId = opcUaNode.NodeId,
				NodeId = opcUaNode.NodeId + 1,
				DisplayName = "变量",
				ParentPath = this.NodeSplitFlag + "PeanutOpcUa",
				Description = "OPC UA变量"
			};
			OpcUaNode opcUaNode3 = new OpcUaNode
			{
				NodeType = OpcUaNodeTypeEnum.Folder,
				NodeName = "Methods",
				ParentNodeId = opcUaNode.NodeId,
				NodeId = opcUaNode.NodeId + 2,
				DisplayName = "方法",
				ParentPath = this.NodeSplitFlag + "PeanutOpcUa",
				Description = "OPC UA方法"
			};
			this.AddNodes(opcUaNode, opcUaNode2, opcUaNode3);
			return opcUaNode;
		}

		protected virtual List<OpcUaNode> CreateVarNodes(OpcUaNode parent)
		{
			//List<OpcUaNode> configNodes = new XmlUtil("OpcUaNodeConfig.config").GetConfigNodes(parent, this.MaxNodeId);
			List<OpcUaNode> configNodes = null;
			//this.AddNodes(configNodes);
			return configNodes;
		}

		protected virtual List<OpcUaNode> CreateVarNodes<T>() where T : class
		{
			List<OpcUaNode> list = new List<OpcUaNode>();
			PropertyInfo[] properties = typeof(T).GetProperties();
			OpcUaApiAttribute customClassAb = BuildAttribute.GetCustomClassAb<OpcUaApiAttribute, T>();
			if (customClassAb == null)
			{
				return new List<OpcUaNode>();
			}
			OpcUaNode opcUaNode = this.CheckFolderExist(customClassAb);
			if (opcUaNode == null)
			{
				throw new Exception("创建目录信息失败!" + customClassAb.FolderPath);
			}
			int num = opcUaNode.NodeId;
			PropertyInfo[] array = properties;
			foreach (PropertyInfo propertyInfo in array)
			{
				num++;
				OpcUaVarNodeAttribute customAb = BuildAttribute.GetCustomAb<T, OpcUaVarNodeAttribute>(propertyInfo);
				if (customAb != null)
				{
					OpcUaNode item = new OpcUaNode
					{
						NodeId = num,
						ParentNodeId = opcUaNode.NodeId,
						NodeName = propertyInfo.Name,
						DisplayName = customAb.DisplayName,
						NodeType = OpcUaNodeTypeEnum.Var,
						ParentPath = customClassAb.FolderPath,
						TypeStr = this.ConvertTypeToNodId(propertyInfo.PropertyType),
						AccessLevels = customAb.AccessLevels,
						UserAccessLevels = customAb.UserAccessLevels
					};
					list.Add(item);
				}
			}
			this._listNotes.AddRange(list);
			return list;
		}

		protected virtual List<OpcUaNode> CreateMethods()
		{
			return new List<OpcUaNode>();
		}

		protected List<OpcUaNode> CreateMethods<T>(T t) where T : class
		{
			OpcUaApiAttribute customClassAb = BuildAttribute.GetCustomClassAb<OpcUaApiAttribute, T>();
			if (customClassAb == null)
			{
				return new List<OpcUaNode>();
			}
			var enumerable = from x in typeof(T).GetMethods()
				select new
				{
					MethodInfo = x,
					OpcUaAttribute = Attribute.GetCustomAttribute(x, typeof(OpcUaMothodNodeAttribute))
				} into x
				where x.OpcUaAttribute != null
				select x;
			OpcUaNode opcUaNode = this.CheckFolderExist(customClassAb);
			if (opcUaNode == null)
			{
				throw new Exception("创建目录信息失败!" + customClassAb.FolderPath);
			}
			int num = opcUaNode.NodeId;
			List<OpcUaNode> list = new List<OpcUaNode>();
			foreach (var each in enumerable)
			{
				num++;
				OpcUaMothodNodeAttribute opcUaMothodNodeAttribute = (OpcUaMothodNodeAttribute)each.OpcUaAttribute;
				MethodNode methodNode = new MethodNode
				{
					NodeType = OpcUaNodeTypeEnum.Method,
					NodeId = num,
					ParentNodeId = opcUaNode.NodeId,
					NodeName = each.MethodInfo.Name,
					ParentPath = opcUaNode.FullName,
					Description = opcUaMothodNodeAttribute.Description,
					DisplayName = opcUaMothodNodeAttribute.DisplayName,
					CallBackMethod = (ISystemContext x, MethodState y, IList<object> z, IList<object> k) => (ServiceResult)each.MethodInfo.Invoke(t, new object[4] { x, y, z, k })
				};
				List<Attribute> list2 = Attribute.GetCustomAttributes(each.MethodInfo).ToList();
				List<Argument> list3 = new List<Argument>();
				List<Argument> list4 = new List<Argument>();
				if (list2.Count > 0)
				{
					list2 = list2.OrderBy((Attribute x) => x.ToString()).ToList();
				}
				foreach (Attribute item2 in list2)
				{
					NodeId nodeId = null;
					Argument item = null;
					ArgumentAttribute argumentAttribute = item2 as ArgumentAttribute;
					if (argumentAttribute != null)
					{
						nodeId = this.ConvertStrToDataTypIs(argumentAttribute.DataType.ToString());
						if (nodeId == null)
						{
							DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(11, 1);
							defaultInterpolatedStringHandler.AppendLiteral("方法输入参数转换失败!");
							defaultInterpolatedStringHandler.AppendFormatted(argumentAttribute.DataType);
							throw new Exception(defaultInterpolatedStringHandler.ToStringAndClear());
						}
						item = new Argument
						{
							Name = argumentAttribute.Name,
							Description = argumentAttribute.Description,
							DataType = nodeId,
							ValueRank = -1
						};
					}
					if (item2 is InpuArgAttribute)
					{
						list3.Add(item);
					}
					else if (item2 is OutputArgAttribute)
					{
						list4.Add(item);
					}
				}
				methodNode.InputArgs = list3.ToArray();
				methodNode.OutputArgs = list4.ToArray();
				list.Add(methodNode);
			}
			return list;
		}

		protected OpcUaNode CheckFolderExist(OpcUaApiAttribute apiInfo)
		{
			if (string.IsNullOrWhiteSpace(apiInfo?.FolderPath))
			{
				return null;
			}
			OpcUaNode opcUaNode = this._listNotes.FirstOrDefault((OpcUaNode x) => x.FullName == apiInfo.FolderPath);
			List<OpcUaNode> list = new List<OpcUaNode>();
			int? num = opcUaNode?.NodeId;
			int num2 = this.MaxNodeId;
			if (opcUaNode == null)
			{
				List<string> buf = (from x in apiInfo.FolderPath.Split(this.NodeSplitFlag.ToCharArray())
					where !string.IsNullOrWhiteSpace(x)
					select x).ToList();
				OpcUaNode opcUaNode2 = null;
				int i;
				for (i = 0; i < buf.Count; i++)
				{
					OpcUaNode opcUaNode3 = this._listNotes.FirstOrDefault((OpcUaNode x) => x.NodeName == buf[i]);
					if (opcUaNode3 != null)
					{
						opcUaNode2 = opcUaNode3;
						continue;
					}
					num2++;
					OpcUaNode opcUaNode4 = new OpcUaNode
					{
						ParentNodeId = (opcUaNode2?.NodeId ?? (-1)),
						ParentPath = opcUaNode2?.FullName,
						NodeId = num2,
						NodeName = buf[i],
						NodeType = OpcUaNodeTypeEnum.Folder,
						Description = apiInfo.Description,
						DisplayName = apiInfo.DisplayName
					};
					list.Add(opcUaNode4);
					opcUaNode2 = opcUaNode4;
				}
				this._listNotes.AddRange(list);
				return list.LastOrDefault();
			}
			return opcUaNode;
		}

		private MethodState CreateMethod(NodeState parent, MethodNode methodNode)
		{
			MethodState methodState = new MethodState(parent);
			methodState.SymbolicName = methodNode.DisplayName;
			methodState.ReferenceTypeId = ReferenceTypeIds.HasComponent;
			methodState.NodeId = new NodeId(methodNode.FullName, base.NamespaceIndex);
			methodState.BrowseName = new QualifiedName(methodNode.NodeName, base.NamespaceIndex);
			methodState.DisplayName = new LocalizedText("en", methodNode.DisplayName);
			methodState.WriteMask = AttributeWriteMask.None;
			methodState.UserWriteMask = AttributeWriteMask.None;
			methodState.Description = methodNode.Description;
			methodState.Executable = true;
			methodState.UserExecutable = true;
			parent?.AddChild(methodState);
			if (methodNode.InputArgs != null)
			{
				methodState.InputArguments = new PropertyState<Argument[]>(methodState);
				methodState.InputArguments.NodeId = new NodeId(methodState.BrowseName.Name + "InArgs", base.NamespaceIndex);
				methodState.InputArguments.BrowseName = "InputArguments";
				methodState.InputArguments.DisplayName = methodState.InputArguments.BrowseName.Name;
				methodState.InputArguments.TypeDefinitionId = VariableTypeIds.PropertyType;
				methodState.InputArguments.ReferenceTypeId = ReferenceTypeIds.HasProperty;
				methodState.InputArguments.DataType = DataTypeIds.Argument;
				methodState.InputArguments.ValueRank = 1;
				methodState.InputArguments.Description = "输入参数";
				methodState.InputArguments.Value = methodNode.InputArgs;
			}
			if (methodNode.OutputArgs != null)
			{
				methodState.OutputArguments = new PropertyState<Argument[]>(methodState);
				methodState.OutputArguments.NodeId = new NodeId(methodState.BrowseName.Name + "OutArgs", base.NamespaceIndex);
				methodState.OutputArguments.BrowseName = "OutputArguments";
				methodState.OutputArguments.DisplayName = methodState.OutputArguments.BrowseName.Name;
				methodState.OutputArguments.TypeDefinitionId = VariableTypeIds.PropertyType;
				methodState.OutputArguments.ReferenceTypeId = ReferenceTypeIds.HasProperty;
				methodState.OutputArguments.DataType = DataTypeIds.Argument;
				methodState.OutputArguments.ValueRank = 1;
				methodState.OutputArguments.Description = "输出参数";
				methodState.OutputArguments.Value = methodNode.OutputArgs;
			}
			if (methodNode.CallBackMethod != null)
			{
				methodState.OnCallMethod = methodNode.CallBackMethod.Invoke;
			}
			return methodState;
		}

		protected virtual string ConvertTypeToNodId(Type type)
		{
			return type.Name;
		}

		protected NodeId ConvertStrToDataTypIs(string type)
		{
			if (string.IsNullOrWhiteSpace(type))
			{
				return null;
			}
			FieldInfo field = typeof(DataTypeIds).GetField(type, BindingFlags.Static | BindingFlags.Public);
			if (field == null)
			{
				return null;
			}
			return (NodeId)field.GetValue(null);
		}

		private void GenerateNodes(List<OpcUaNode> nodes, IList<IReference> references)
		{
			List<OpcUaNode> list = nodes.Where((OpcUaNode d) => d.ParentNodeId == -1).ToList();
			foreach (OpcUaNode item in list)
			{
				try
				{
					FolderState folderState = this.CreateFolder(null, item);
					folderState.AddReference(35u, isInverse: true, ObjectIds.ObjectsFolder);
					references.Add(new NodeStateReference(35u, isInverse: false, folderState.NodeId));
					folderState.EventNotifier = 1;
					this.AddRootNotifier(folderState);
					this.CreateNodes(folderState, item, nodes);
					this._folderDic.Add(item.NodeName, folderState);
					this.AddPredefinedNode(base.SystemContext, folderState);
				}
				catch (Exception ex)
				{
					Console.WriteLine(ex.ToString());
					throw new Exception("generate nodes failed!", ex);
				}
			}
		}

		private void CreateNodes(FolderState parentRoot, OpcUaNode parentNode, List<OpcUaNode> nodes)
		{
			List<OpcUaNode> list = nodes.Where((OpcUaNode x) => x.ParentNodeId == parentNode.NodeId).ToList();
			foreach (OpcUaNode item in list)
			{
				try
				{
					switch (item.NodeType)
					{
					case OpcUaNodeTypeEnum.Folder:
					{
						FolderState folderState = this.CreateFolder(parentRoot, item);
						if (!this._folderDic.ContainsKey(item.NodeName))
						{
							this._folderDic.Add(item.NodeName, folderState);
						}
						this.CreateNodes(folderState, item, nodes);
						break;
					}
					case OpcUaNodeTypeEnum.Var:
					{
						NodeId nodeId = this.ConvertStrToDataTypIs(item.TypeStr);
						if (nodeId == null)
						{
							return;
						}
						BaseDataVariableState baseDataVariableState = this.CreateVariable(parentRoot, item, nodeId, -1);
						baseDataVariableState.Value = EnDeCode.GetDefaultTypeValue(item.TypeStr);
						if (!this._varDic.ContainsKey(item.FullName))
						{
							this._varDic.Add(item.FullName, baseDataVariableState);
						}
						else
						{
							Console.WriteLine("变量重复" + item.FullName);
						}
						break;
					}
					case OpcUaNodeTypeEnum.Method:
					{
						MethodNode methodNode = item as MethodNode;
						if (methodNode != null)
						{
							MethodState value = this.CreateMethod(parentRoot, methodNode);
							if (!this._methodDic.ContainsKey(methodNode.FullName))
							{
								this._methodDic.Add(methodNode.FullName, value);
							}
							else
							{
								Console.WriteLine("方法重复" + methodNode.FullName);
							}
						}
						break;
					}
					}
				}
				catch (Exception innerException)
				{
					throw new Exception("create nodes failed！", innerException);
				}
			}
		}

		private FolderState CreateFolder(NodeState parent, OpcUaNode node)
		{
			FolderState folderState = new FolderState(parent);
			folderState.SymbolicName = node.DisplayName;
			folderState.ReferenceTypeId = 35u;
			folderState.TypeDefinitionId = ObjectTypeIds.FolderType;
			folderState.NodeId = new NodeId(node.FullName, base.NamespaceIndex);
			folderState.BrowseName = new QualifiedName(node.NodeName, base.NamespaceIndex);
			folderState.DisplayName = new LocalizedText("en", node.DisplayName);
			folderState.WriteMask = AttributeWriteMask.None;
			folderState.UserWriteMask = AttributeWriteMask.None;
			folderState.EventNotifier = 0;
			folderState.Description = node.Description;
			parent?.AddChild(folderState);
			return folderState;
		}

		public byte? ConvertToAccessLevel(string name)
		{
			return (byte?)typeof(AccessLevels).GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy)?.GetValue(null);
		}

		private BaseDataVariableState CreateVariable(NodeState parent, OpcUaNode uaNode, NodeId dataType, int valueRank)
		{
			byte? b = this.ConvertToAccessLevel(uaNode.AccessLevels);
			byte? b2 = this.ConvertToAccessLevel(uaNode.UserAccessLevels);
			BaseDataVariableState baseDataVariableState = new BaseDataVariableState(parent);
			baseDataVariableState.SymbolicName = uaNode.DisplayName;
			baseDataVariableState.ReferenceTypeId = 35u;
			baseDataVariableState.TypeDefinitionId = VariableTypeIds.BaseDataVariableType;
			baseDataVariableState.NodeId = new NodeId(uaNode.FullName, base.NamespaceIndex);
			baseDataVariableState.BrowseName = new QualifiedName(uaNode.NodeName, base.NamespaceIndex);
			baseDataVariableState.DisplayName = new LocalizedText("en", uaNode.DisplayName);
			baseDataVariableState.WriteMask = AttributeWriteMask.Description | AttributeWriteMask.DisplayName;
			baseDataVariableState.UserWriteMask = AttributeWriteMask.Description | AttributeWriteMask.DisplayName;
			baseDataVariableState.Description = uaNode.Description;
			baseDataVariableState.DataType = dataType;
			baseDataVariableState.ValueRank = valueRank;
			baseDataVariableState.AccessLevel = b ?? 1;
			baseDataVariableState.UserAccessLevel = b2 ?? 1;
			baseDataVariableState.Historizing = false;
			baseDataVariableState.StatusCode = 0u;
			baseDataVariableState.Timestamp = DateTime.Now;
			baseDataVariableState.OnWriteValue = OnWriteDataValue;
			switch (valueRank)
			{
			case 1:
				baseDataVariableState.ArrayDimensions = new ReadOnlyList<uint>(new List<uint> { 0u });
				break;
			case 2:
				baseDataVariableState.ArrayDimensions = new ReadOnlyList<uint>(new List<uint> { 0u, 0u });
				break;
			}
			parent?.AddChild(baseDataVariableState);
			return baseDataVariableState;
		}

		protected virtual ServiceResult OnWriteDataValue(ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp)
		{
			BaseDataVariableState baseDataVariableState = node as BaseDataVariableState;
			try
			{
				Opc.Ua.TypeInfo typeInfo = Opc.Ua.TypeInfo.IsInstanceOfDataType(value, baseDataVariableState.DataType, baseDataVariableState.ValueRank, context.NamespaceUris, context.TypeTable);
				if (typeInfo == null || typeInfo == Opc.Ua.TypeInfo.Unknown)
				{
					return 2155085824u;
				}
				return ServiceResult.Good;
			}
			catch (Exception)
			{
				return 2155085824u;
			}
		}

		public override void HistoryRead(OperationContext context, HistoryReadDetails details, TimestampsToReturn timestampsToReturn, bool releaseContinuationPoints, IList<HistoryReadValueId> nodesToRead, IList<HistoryReadResult> results, IList<ServiceResult> errors)
		{
			ReadProcessedDetails readProcessedDetails = details as ReadProcessedDetails;
			if (readProcessedDetails == null || readProcessedDetails.StartTime == DateTime.MinValue || readProcessedDetails.EndTime == DateTime.MinValue)
			{
				errors[0] = 2154954752u;
				return;
			}
			for (int i = 0; i < nodesToRead.Count; i++)
			{
				int millisecond = readProcessedDetails.StartTime.Millisecond;
				double num = millisecond + DateTime.Now.Millisecond;
				Opc.Ua.KeyValuePair body = new Opc.Ua.KeyValuePair
				{
					Key = new QualifiedName(nodesToRead[i].NodeId.Identifier.ToString()),
					Value = num
				};
				results[i] = new HistoryReadResult
				{
					StatusCode = 0u,
					HistoryData = new ExtensionObject(body)
				};
				errors[i] = 0u;
				nodesToRead[i].Processed = true;
			}
		}

		public string NodeCombine(OpcUaApiAttribute opcUaApiInfo, string varName)
		{
			if (opcUaApiInfo == null || string.IsNullOrWhiteSpace(varName))
			{
				return null;
			}
			return opcUaApiInfo?.FolderPath + this.NodeSplitFlag + varName;
		}

		public OperateResult WriteMulti<T>(T entity, Expression<Func<T, object>> exp) where T : class, new()
		{
			List<string> columnNames = LambdaResolver.GetColumnNames(exp);
			return this.WriteMulti(entity, columnNames);
		}

		public OperateResult WriteMulti<T>(T entity) where T : class, new()
		{
			List<string> list = new List<string>();
			PropertyInfo[] properties = typeof(T).GetProperties();
			PropertyInfo[] array = properties;
			foreach (PropertyInfo propertyInfo in array)
			{
				list.Add(propertyInfo.Name);
			}
			return this.WriteMulti(entity, list);
		}

		protected OperateResult WriteMulti<T>(T entity, List<string> propertyNames) where T : class, new()
		{
			OpcUaApiAttribute value = null;
			StringBuilder stringBuilder = new StringBuilder();
			if (!this._dicOpcApi.TryGetValue(typeof(T), out value))
			{
				value = BuildAttribute.GetCustomClassAb<OpcUaApiAttribute, T>();
				if (value == null)
				{
					return new OperateResult
					{
						Message = "缺少OpcUaApiAttribute修饰!"
					};
				}
				this._dicOpcApi.Add(typeof(T), value);
			}
			PropertyInfo[] properties = typeof(T).GetProperties();
			foreach (string each in propertyNames)
			{
				string text = this.NodeCombine(value, each);
				if (text == null)
				{
					continue;
				}
				if (this._varDic.TryGetValue(text, out var value2))
				{
					PropertyInfo propertyInfo = properties.First((PropertyInfo x) => x.Name == each);
					this.Update(value2, propertyInfo.GetValue(entity));
					continue;
				}
				StringBuilder stringBuilder2 = stringBuilder;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(6, 2, stringBuilder2);
				handler.AppendLiteral("缺少目标节点");
				handler.AppendFormatted(text);
				handler.AppendFormatted(Environment.NewLine);
				stringBuilder2.Append(ref handler);
			}
			return new OperateResult
			{
				IsSuccess = true,
				Message = stringBuilder.ToString()
			};
		}

		protected void Update(BaseVariableState variable, object value)
		{
			if (variable == null)
			{
				throw new ArgumentNullException("variable");
			}
			if (!object.Equals(variable.Value, value))
			{
				variable.Value = value;
				DateTime dateTime = DateTime.Parse(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"));
				variable.Timestamp = DateTime.Now;
				variable.ClearChangeMasks(base.SystemContext, includeChildren: false);
			}
		}

		public OperateResult WriteMulti(Dictionary<string, object> dic)
		{
			StringBuilder stringBuilder = new StringBuilder();
			foreach (string key in dic.Keys)
			{
				if (this._varDic.TryGetValue(key, out var value))
				{
					this.Update(value, dic[key]);
					continue;
				}
				StringBuilder stringBuilder2 = stringBuilder;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(6, 2, stringBuilder2);
				handler.AppendLiteral("缺少目标节点");
				handler.AppendFormatted(key);
				handler.AppendFormatted(Environment.NewLine);
				stringBuilder2.Append(ref handler);
			}
			return new OperateResult
			{
				IsSuccess = true,
				Message = stringBuilder.ToString()
			};
		}

		public BaseDataVariableState TryGetVarState(string varAdr)
		{
			if (this._varDic.TryGetValue(varAdr, out var value))
			{
				return value;
			}
			return null;
		}

		public MethodState TryGetMethodState(string methodAdr)
		{
			if (this._methodDic.TryGetValue(methodAdr, out var value))
			{
				return value;
			}
			return null;
		}
	}
}
